package org.sjs.dreamfly.biz.movie

import android.webkit.WebView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.sjs.dreamfly.app.MovieListLoadedEvent
import org.sjs.dreamfly.app.defaultEventBus
import org.sjs.dreamfly.browser.WebLocation
import org.sjs.dreamfly.common.base.BaseViewModel
import org.sjs.dreamfly.common.util.LogUtil
import org.sjs.dreamfly.data.AppDataBase
import org.sjs.dreamfly.data.Config
import org.sjs.dreamfly.model.MovieInfo
import org.sjs.dreamfly.network.RetrofitUtil
import org.sjs.dreamfly.network.api.IXiGuaApi
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger

class MovieListViewModel : BaseViewModel() {

    private var loader: Loader? = null
    private val movieList = mutableListOf<MovieInfo>()
    private var channelType: String = Config.defaultChannelType4XiGua
    private val movieDao by lazy {
        AppDataBase.getDatabase().movieDao()
    }

    fun init(channelType: String) {
        this.channelType = channelType
    }

    fun getMovieList(): List<MovieInfo> {
        return movieList
    }

    fun onMovieListLoaded(list: List<MovieInfo>) {
        movieList.addAll(list)
        mainScope.launch(Dispatchers.IO) {
            list.forEach {
                movieDao.insert(it, channelType)
            }
        }

        loader?.onLoaded()
    }
    private suspend fun loadIXiGuaList(): List<MovieInfo> = withContext(Dispatchers.IO) {
        val list = mutableListOf<MovieInfo>()
        try {
            val localList = movieDao.getMovieList(channelType)
            if (localList.isNotEmpty()) {
                LogUtil.d("load from local database size:$localList")
                list.addAll(localList)
            } else {
                val response = RetrofitUtil.getIXiGuaRetrofit().create(IXiGuaApi::class.java)
                    .loadMovieHome(
                        referer = MovieConstants.getXiGuaChannelHomePageUrl(channelType),
                        channelType = channelType
                    ).execute()
                if ((response.body()?.data?.getMovieList()?.size ?: 0) > 0) {
                    response.body()?.data?.getMovieList()?.forEach {
                        list.add(it)
                        movieDao.insert(it, channelType)
                    }
                }
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return@withContext list
    }

    suspend fun loadMovieList(): List<MovieInfo> {
        movieList.clear()
        movieList.addAll(loadIXiGuaList())
        return movieList
    }

    suspend fun loadMore(): Boolean {
        if (loader is RetrofitLoader) {
            return withContext(Dispatchers.IO) {
                return@withContext loader?.loadMore(channelType)?:false
            }
        } else {
            return loader?.loadMore(channelType)?:false
        }
    }

    fun onWebLoadMore(view: WebView, url: String): Boolean  {
        if (loader == null) {
            loader = WebViewLoader(view, url)
        }
        if (loader is WebViewLoader) {
            return loader?.loadMore(channelType)?: false
        }
        return false
    }

    abstract class Loader {
        protected var isWebLoadingMore = AtomicBoolean(false)
        protected var pageIndex = AtomicInteger(0)
        protected var pageSize = AtomicInteger(18)
        abstract fun loadMore(channelType: String): Boolean
        fun onLoaded() {
            pageIndex.incrementAndGet()
            isWebLoadingMore.set(false)
        }
    }
    class WebViewLoader(webView: WebView, private val originUrl: String): Loader() {
        //    https://www.ixigua.com/na/monorepo/bff/api/lvideo_filter/get_category_lvideos?limit=18&offset=0&pinyin=dianshiju&filters={%22type%22:%22%E7%94%B5%E8%A7%86%E5%89%A7%22,%22area%22:%22%E5%85%A8%E9%83%A8%E5%9C%B0%E5%8C%BA%22,%22tag%22:%22%E5%85%A8%E9%83%A8%E7%B1%BB%E5%9E%8B%22,%22sort%22:%22%E7%BB%BC%E5%90%88%E6%8E%92%E5%BA%8F%22,%22paid%22:%22%E5%85%A8%E9%83%A8%E8%B5%84%E8%B4%B9%22}&aid=1768
//    https://www.ixigua.com/na/monorepo/bff/api/lvideo_filter/get_category_lvideos?limit=18&offset=0&pinyin=dianshiju&filters={"type":"电视剧","area":"全部地区","tag":"全部类型","sort":"综合排序","paid":"全部资费"}&aid=1768, originUrl:https://www.ixigua.com/stream/cinema/filter/dianshiju
        private var webView: WeakReference<WebView>? = null
        init {
            this.webView = WeakReference(webView)
        }
        override fun loadMore(channelType: String): Boolean {
            if (isWebLoadingMore.get()) return false
            val url = originUrl.replace("offset=0", "offset=$pageIndex").replace("limit=18", "limit=$pageSize")
            webView?.get()?.evaluateJavascript(MovieConstants.jsCodeForXiGuaMovieLoadMore(url)){}
            isWebLoadingMore.set(true)
            return true
        }
    }

    class RetrofitLoader : Loader() {
        override fun loadMore(channelType: String): Boolean {
            if (isWebLoadingMore.get()) return false
            isWebLoadingMore.set(true)
            try {
                val call = RetrofitUtil.getIXiGuaRetrofit().create(IXiGuaApi::class.java)
                    .loadMovieFeed(
                        referer = MovieConstants.getXiGuaChannelHomePageUrl(channelType),
                        channelId = MovieConstants.getChannelId(channelType),
                        queryCount = pageIndex.get(),
                        limit = pageSize.get(),
//                    msToken = "i_N1E07bhch-1qKgQ41KmUoRVBe9brlATUPiCf_c_HFziUYxZ3a-O0ie-a9a9XGjDoi9S06_hubuuMBklIeMMXdElKyvAwzVkfFmXMz7oVQO4vbhIhU0dF7N2rwy2g==\n",
//                    bogus = "DFSzswVY22hANnjEtHhOvFm4pIk0",
//                    signature = "_02B4Z6wo00001ko8-4AAAIDC0lds8XHykrJKPP8AAPZZLZsykc9JHem4u.KdjRdxXxUFn8wdE2IJ18y7mKqfh30GopSgB6-ce3hCcMlwJpu2l-J.uP-.W9VkglVkg.FZV2rqGd7JYQvbguX0b5"
                    )
                val response = call.execute()
                if ((response.body()?.data?.getMovieList()?.size?: 0) > 0) {
                    response.body()?.data?.getMovieList()?.let {
                        val location = WebLocation()
                        call.request().url.apply {
                            location.href = this.toString()
                            location.host = this.host
                        }
                        defaultEventBus.post(MovieListLoadedEvent(location, it))
                        return true
                    }
                }
            } catch (e: Exception ) {
                e.printStackTrace()
            }
            return false
        }
    }
}